2023 Hyundai mobis Algorithm

상담원(Lv.3)
https://school.programmers.co.kr/learn/courses/30/lessons/214288
#include <iostream>
#include <algorithm>
#include <numeric>
#include <functional>
#include <utility>
#include <vector>
struct Time {
Time(int b, int d): begin(b), duration(d) {}
int begin, duration;
};
bool cmpTime(const Time& t1, const Time& t2) { return t1.begin<t2.begin; }
class Type {
public:
Type(int num): typeNum(num) {}
void push(const Time& time) {
times.push_back(time);
std::sort(times.begin(), times.end(), cmpTime);
}
int waitTime(int num) {
int time=0;
std::vector<int> empl(num, 0);
for(auto iter=times.begin(); iter!=times.end(); ++iter) {
std::sort(empl.begin(), empl.end());
if(iter->begin>empl[0]) {
empl[0]=iter->begin+iter->duration;
} else {
time+=empl[0]-iter->begin;
empl[0]+=iter->duration;
}
}
return time;
}
private:
std::vector<Time> times;
int typeNum;
};
auto oneAddVec = [](const std::vector<int>& input) {
std::vector<int> nV = input;
for (int i = 0; i < nV.size(); ++i)
nV[i]++;
return nV;
};
auto bigGapInd = [](const std::vector<int> &v1, const std::vector<int> &v2) {
assert(v1.size() == v2.size());
int index = -1, value = -1;
for (int i = 0; i < v1.size(); ++i) {
int gap = v1[i] - v2[i];
if (gap > value) {
value=v1[i]-v2[i];
index=i;
}
}
return index;
};
class Scheduler {
public:
Scheduler(int k) : k(k) {
for(int i=0; i<k; ++i) types.push_back(Type(i+1));
}
void push(const int t, const int d, const int type) {
Time time(t, d);
types[type-1].push(time);
}
std::vector<int> tft(std::vector<int> emplForType) {
std::vector<int> tftV(emplForType.size(), 0);
for(int i=0; i<emplForType.size(); ++i) {
tftV[i]=this->types[i].waitTime(emplForType[i]);
}
return tftV;
}
int minWaitTime(int num) {
std::vector<int> emplForType(this->k, 1);
std::vector<int> timeForType=tft(emplForType);
std::vector<int> nextTFT(this->k, 0);
for(int i=0; i<num-3; ++i) {
int index=bigGapInd(timeForType, tft(oneAddVec(emplForType)));
emplForType[index]++;
timeForType=tft(emplForType);
}
for(int i=0; i<this->k; ++i) std::cout<<emplForType[i]<<std::endl;
return std::accumulate(timeForType.begin(), timeForType.end(), 0);
}
private:
std::vector<Type> types;
int k;
};
int main(void) {
int k=3, n=5;
Scheduler scheduler(k);
scheduler.push(10, 60, 1);
scheduler.push(15, 100, 3);
scheduler.push(20, 30, 1);
scheduler.push(30, 50, 3);
scheduler.push(50, 40, 1);
scheduler.push(60, 30, 2);
scheduler.push(65, 30, 1);
scheduler.push(70, 100, 2);
int result=scheduler.minWaitTime(n);
std::cout<<"Min Waiting Time is "<<result<<std::endl;
return 0;
}
air conditioner(Lv. 3)
https://school.programmers.co.kr/learn/courses/30/lessons/214289
#include <iostream>
#include <algorithm>
#include <numeric>
#include <utility>
#include <limits>
#include <vector>
class Tmpl {
public:
Tmpl(int curT, int minT, int maxT) : curT(curT), outT(curT), minT(minT), maxT(maxT) { this->setTempDir(); }
bool isFine(void) const;
Tmpl mntn(void);
Tmpl off(void);
Tmpl on(void);
int curT;
private:
void setTempDir(void);
const int minT, maxT, outT;
int /*curT,*/ tempDir;
};
void Tmpl::setTempDir(void) {
this->tempDir= (curT >= minT && curT <= maxT) ? 0 :
(curT < minT) ? 1 : -1;
}
bool Tmpl::isFine(void) const {
return this->curT>=minT && this->curT<=maxT;
}
Tmpl Tmpl::mntn(void) { return Tmpl(*this); }
Tmpl Tmpl::off(void) {
Tmpl newTmpl=(*this);
newTmpl.curT -= (this->curT==this->outT ? 0 : this->tempDir);
return newTmpl;
}
Tmpl Tmpl::on(void) {
Tmpl newTmpl=(*this);
newTmpl.curT += this->tempDir;
return newTmpl;
}
class AirCndt {
public:
AirCndt(int a, int b, std::vector<bool> onBoard): a(a), b(b), onBoard(onBoard) {}
int findMinFee(int tmp, int t1, int t2);
private:
void rcsFindMin(Tmpl tmpl, int price, int index, int& result);
std::vector<bool> onBoard;
const int a, b;
};
void AirCndt::rcsFindMin(Tmpl tmpl, int price, int index, int& result) {
if(this->onBoard[index] && !tmpl.isFine()) return;
if(index==this->onBoard.size()-1) {
if(result > price) result=price;
return;
}
this->rcsFindMin(tmpl.mntn(), price+this->b, index+1, result);
this->rcsFindMin(tmpl.on(), price+this->a, index+1, result);
this->rcsFindMin(tmpl.off(), price, index+1, result);
}
int AirCndt::findMinFee(int tmp, int t1, int t2) {
Tmpl tmpl(tmp, t1, t2);
int result=std::numeric_limits<int>::max();
rcsFindMin(tmpl, 0, 0, result);
return result;
}
int main(void) {
int tmp=28, t1=18, t2=26, a=10, b=8, result;
std::vector<bool> onBoard={0, 0, 1, 1, 1, 1, 1};
AirCndt aircndt(a, b, onBoard);
result=aircndt.findMinFee(tmp, t1, t2);
std::cout<<"result: "<<result<<std::endl;
return 0;
}
Calculate Slope (Lv. 4)
https://school.programmers.co.kr/learn/courses/30/lessons/214290
#include <iostream>
#include <algorithm>
#include <numeric>
#include <utility>
#include <functional>
#include <vector>
#include <string>
#define MODNUM 1000000007
struct Point {
Point(int x, int y): x(x), y(y) {}
Point cmove(int dx, int dy) const;
int x, y;
};
Point Point::cmove(int dx, int dy) const {
return Point(x+dx, y+dy);
}
struct StoE {
StoE(Point p1, Point p2): p1(p1), p2(p2) {}
Point p1, p2;
};
struct Drctn {
Drctn(int xsz, int ysz) : xsz(xsz), ysz(ysz) {}
bool possible(const Point& point);
std::vector<int> possibleDir(const Point& point);
const int dx[4]={0, 1, 0, -1};
const int dy[4]={1, 0, -1, 0};
const int xsz, ysz;
};
bool Drctn::possible(const Point& point) {
return point.x < this->xsz && point.x >= 0 && point.y < this->ysz && point.y >=0;
}
std::vector<int> Drctn::possibleDir(const Point& point) {
std::vector<int> psV;
for(int i=0; i<4; ++i) {
if(this->possible(point.cmove(dx[i], dy[i]))) psV.push_back(i);
}
return psV;
}
class Grid {
public:
Grid(std::vector<std::vector<int>> grid, std::vector<int> d) :
grid(grid), drctn(grid.size(), grid[0].size()), d(d) {}
int getValue(const Point& point) const;
bool gapBtw(const Point& p1, const Point& p2, int gap);
void findRoute(int, const Point&, const Point&, std::vector<StoE>&);
std::vector<StoE> possibleRouteOne(void);
void sumUpCases(const std::vector<StoE>&, const Point&, const int k, int& sum);
int possibleRoute(int k);
private:
const std::vector<std::vector<int>> grid;
const std::vector<int> d;
Drctn drctn;
};
int Grid::getValue(const Point& point) const {
assert(point.x < this->grid.size() && point.y < this->grid[0].size());
return this->grid[point.x][point.y];
}
bool Grid::gapBtw(const Point& p1, const Point& p2, int gap) {
return this->getValue(p2)-this->getValue(p1) == gap;
}
void Grid::findRoute(int index, const Point& pBeg, const Point& pCur, std::vector<StoE>& routeK) {
if(index==this->d.size()) {
routeK.push_back(StoE(pBeg, pCur));
return;
}
std::vector<int> possibleDir=this->drctn.possibleDir(pCur);
for(int dir : possibleDir) {
if(gapBtw(pCur, pCur.cmove(drctn.dx[dir], drctn.dy[dir]), this->d[index])) {
this->findRoute(index+1, pBeg, pCur.cmove(drctn.dx[dir], drctn.dy[dir]), routeK);
}
}
}
std::vector<StoE> Grid::possibleRouteOne(void) {
std::vector<StoE> routeOneK;
for(int i=0; i<this->grid.size(); ++i) {
for(int j=0; j<this->grid[0].size(); ++j) {
findRoute(0, Point(i, j), Point(i, j), routeOneK);
}
}
return routeOneK;
}
auto stoeCounter = [](const std::vector<StoE> &stoes, const Point &point) {
int count = 0;
for (StoE stoe : stoes) {
if (point.x == stoe.p1.x && point.y == stoe.p1.y)
count++;
}
return count;
};
void Grid::sumUpCases(const std::vector<StoE>& stoes, const Point& curP, const int k, int& sum) {
if(k==1) {
sum+=stoeCounter(stoes, curP);
sum%=MODNUM;
return;
}
for(StoE stoe : stoes) {
if(stoe.p1.x==curP.x && stoe.p1.y==curP.y) this->sumUpCases(stoes, Point(stoe.p2.x, stoe.p2.y), k-1, sum);
}
}
int Grid::possibleRoute(int k) {
int sum=0;
std::vector<StoE> stoes=this->possibleRouteOne();
for(StoE stoe: stoes) {
this->sumUpCases(stoes, stoe.p2, k-1, sum);
}
return sum;
}
int main(void) {
std::vector<std::vector<int>> grid1={
{3, 4, 6, 5, 3},
{3, 5, 5, 3, 6},
{5, 6, 4, 3, 6},
{7, 4, 3, 5, 0}
};
std::vector<int> d1={1, -2, -1, 0, 2};
int k1=2;
std::vector<std::vector<int>> grid2={
{3, 6, 11, 12},
{4, 8, 15, 10},
{2, 7, 0, 16}
};
std::vector<int> d2={1, -2, 5};
int k2=3;
std::vector<std::vector<int>> grid3={
{0, 0, 0},
{1, 0, 0},
{0, 0, 0},
{0, 0, 1},
{1, 0, 0}
};
std::vector<int> d3={0, 0, 1, -1, 0, 0, 1, -1};
int k3=10;
Grid system(grid1, d1);
int possible=system.possibleRoute(k1);
std::cout<<"Possible route = "<<possible<<std::endl;
return 0;
}
Set And Query (Lv. 5)
https://school.programmers.co.kr/learn/courses/30/lessons/214291
#include <iostream>
#include <algorithm>
#include <numeric>
#include <utility>
#include <vector>
#include <map>
#include <string>
struct Query {
Query(int q, int x, int y);
int operator[](int index) const;
int query[3];
};
Query::Query(int q, int x, int y) {
this->query[0]=q;
this->query[1]=x;
this->query[2]=y;
}
int Query::operator[](int index) const {
return this->query[index];
}
struct Set {
Set(void) {}
Set(int value, int qNum);
void push(int value, int qNum);
void mergeSet(const Set& other, int qNum);
bool isMember(int value);
Set removeBtwReturn(const int x, const int y, const int qNum);
std::map<int, int> set;
};
Set::Set(int value, int qNum) { this->set[value] = qNum; }
void Set::push(int value, int qNum) { this->set[value] = qNum; }
void Set::mergeSet(const Set& other, int qNum) {
for(auto iter=other.set.begin(); iter!=other.set.end(); ++iter) {
this->set[iter->first]=qNum;
}
}
Set Set::removeBtwReturn(const int x, const int y, const int qNum) {
Set newSet;
int min=this->set[x], max=this->set[y];
for(auto iter=this->set.begin(); iter!=this->set.end(); ++iter) {
if(iter->second >= min && iter->second <= max) newSet.push(iter->first, qNum);
}
for(auto iter=newSet.set.begin(); iter!=newSet.set.end(); ++iter) {
this->set.erase(iter->first);
}
return newSet;
}
bool Set::isMember(int value) {
for(auto iter=this->set.begin(); iter!=this->set.end(); ++iter) {
if(iter->first==value) return true;
}
return false;
}
class Sets {
public:
Sets(int n);
std::vector<std::string> procQueries(const std::vector<Query>& queries);
private:
void queryOne(const int x, const int y, const int qNum);
void queryTwo(const int x, const int y, const int);
void queryThird(const int x, const int y, std::vector<std::string>&);
void procQuery(const Query& query, std::vector<std::string>&, const int);
void mergeSets(int s1, int s2, int qNum);
int findSetAsIndex(int value);
std::vector<Set> sets;
};
auto printSets = [](const std::vector<Set> sets) {
for (int i = 0; i < sets.size(); ++i) {
std::cout << "Set " << i << '\n';
for (auto iter = sets[i].set.begin(); iter != sets[i].set.end(); ++iter)
std::cout << iter->first << ' ';
std::cout<<std::endl;
}
};
Sets::Sets(int n) {
for(int i=0; i<n; ++i) this->sets.push_back(Set(i, -1));
}
void Sets::procQuery(const Query& query, std::vector<std::string>& result, const int qNum) {
if(query[0]==1) queryOne(query[1], query[2], qNum);
else if(query[0]==2) queryTwo(query[1], query[2], qNum);
else if(query[0]==3) queryThird(query[1], query[2], result);
}
std::vector<std::string> Sets::procQueries(const std::vector<Query>& queries) {
std::vector<std::string> result;
for(int ind=0; ind<queries.size(); ++ind) {
this->procQuery(queries[ind], result, ind);
// printSets(this->sets);
}
return result;
}
void Sets::mergeSets(int idx1, int idx2, int qNum) {
this->sets[idx1].mergeSet(this->sets[idx2], qNum);
this->sets.erase(this->sets.begin()+idx2);
}
int Sets::findSetAsIndex(int value) {
for(int i=0; i<this->sets.size(); ++i) {
if(sets[i].isMember(value)) return i;
}
return -1;
}
void Sets::queryOne(const int x, const int y, const int qNum) {
int xs=this->findSetAsIndex(x);
int ys=this->findSetAsIndex(y);
if(xs!=ys) {
this->mergeSets(xs, ys, qNum);
}
}
void Sets::queryTwo(const int x, const int y, const int qNum) {
int index=this->findSetAsIndex(x);
assert(index==this->findSetAsIndex(y));
Set newSet=this->sets[index].removeBtwReturn(x, y, qNum);
this->sets.push_back(newSet);
}
void Sets::queryThird(const int x, const int y, std::vector<std::string>& result) {
result.push_back(this->findSetAsIndex(x)==this->findSetAsIndex(y) ? "Yes" : "No");
}
int main(void) {
int n1=4;
std::vector<Query> queries1={
{3, 2, 3},
{1, 3, 2},
{3, 2, 3},
{1, 2, 0},
{3, 0, 1},
{2, 2, 0},
{3, 2, 3},
{3, 0, 2}
};
int n2=7;
std::vector<Query> queries2={
{1, 0, 1},
{1, 2, 3},
{3, 1, 3},
{1, 2, 0},
{3, 1, 3},
{1, 1, 5},
{1, 5, 4},
{3, 4, 5},
{2, 2, 5},
{3, 4, 5}
};
Sets sets(n2);
std::vector<std::string> result=sets.procQueries(queries2);
for(std::string text: result) std::cout<<text<<' ';
std::cout<<std::endl;
return 0;
}
Design Racing Track (Lv. 5)
https://school.programmers.co.kr/learn/courses/30/lessons/214292
#include <iostream>
#include <algorithm>
#include <numeric>
#include <utility>
#include <functional>
#include <limits>
#include <vector>
class PossibleSeq {
public:
PossibleSeq(const std::vector<int>& road);
int findMax(void);
private:
std::vector<int> road;
};
PossibleSeq::PossibleSeq(const std::vector<int>& road): road(road) {
std::sort(this->road.begin(), this->road.end());
}
auto findMinSlope(std::vector<int> vec) {
int min=std::numeric_limits<int>::max();
for(int i=0; i<vec.size()-1; ++i) {
int gap=std::abs(vec[i+1]-vec[i]);
min= min>gap ? gap : min;
}
return min;
}
int PossibleSeq::findMax(void) {
int max=-1;
do {
int minSlope=findMinSlope(this->road);
if(max<minSlope) max=minSlope;
} while(std::next_permutation(this->road.begin(), this->road.end()));
return max;
}
int main(void) {
std::vector<int> heights1={1, 8, 5};
std::vector<int> heights2={11, 6, 4, 11};
std::vector<int> heights3={9, 9, 9, 9, 30};
PossibleSeq possibleSeq(heights3);
int result=possibleSeq.findMax();
std::cout<<"Result: "<<result<<std::endl;
return 0;
}
Most Important(Sensitive) Road (Lv. 5)
https://school.programmers.co.kr/learn/courses/30/lessons/214293
#include <iostream>
#include <algorithm>
#include <numeric>
#include <utility>
#include <functional>
#include <limits>
#include <vector>
#include <map>
#include <string>
struct RoadStatus {
RoadStatus(int length, int trafficJam): length(length), trafficJam(trafficJam) {}
int timeCost(void) const;
int length, trafficJam;
};
int RoadStatus::timeCost(void) const { return this->length + this->trafficJam; }
struct Node {
Node(int num): num(num) {}
void connect(int, int ,int);
void disconnect(int);
void changeJam(int, int);
int num;
std::vector<std::pair<int, RoadStatus>> road;
};
void Node::connect(int node, int length, int trafficJam) {
this->road.push_back(std::make_pair(node, RoadStatus(length, trafficJam)));
}
void Node::disconnect(int node) {
for(auto iter=this->road.begin(); iter!=this->road.end(); ++iter) {
if(iter->first==node) {
this->road.erase(iter);
return;
}
}
}
void Node::changeJam(int node, int jam) {
for(int i=0; i<road.size(); ++i) {
if(road[i].first==node) road[i].second.trafficJam=jam;
}
perror("No road");
}
class Traffic {
public:
Traffic(int nodeNum);
void update(std::vector<std::vector<int>>);
std::vector<int> mostSensitiveRoad(void);
private:
std::vector<std::pair<int, std::vector<Node>>> allNodes(std::vector<int> path);
std::vector<Node> retUpdate(std::vector<std::vector<int>>);
int nodeNum, totalTraffic=0;
std::vector<Node> nodes;
std::vector<std::vector<int>> roadsInfo;
};
Traffic::Traffic(int nodeNum): nodeNum(nodeNum) {
for(int i=1; i<=nodeNum; ++i) this->nodes.push_back(Node(i));
}
void Traffic::update(std::vector<std::vector<int>> roadsInfo) {
this->roadsInfo=roadsInfo;
for(std::vector<int> roadInfo: roadsInfo) {
this->totalTraffic+=roadInfo[3];
this->nodes[roadInfo[0]-1].connect(roadInfo[1], roadInfo[2], roadInfo[3]);
this->nodes[roadInfo[1]-1].connect(roadInfo[0], roadInfo[2], roadInfo[3]);
}
}
auto haveBeen = [](const std::vector<int> path, int value) {
for (int been : path)
if (been == value)
return true;
return false;
};
using PathAndTime = std::pair<std::vector<int>, int>;
auto pushVec = [](const std::vector<int> &vec, int value) {
std::vector<int> retVec = vec;
retVec.push_back(value);
return retVec;
};
void recursiveFind(const std::vector<Node>& nodes, int end, std::vector<int> path, int sum, std::vector<int>& minPath, int& min) {
if(path.back()==end) {
if(sum<min) {
min=sum;
minPath=path;
}
return;
}
for(auto iter=nodes[path.back()-1].road.begin(); iter!=nodes[path.back()-1].road.end(); ++iter) {
if(!haveBeen(path, iter->first)) recursiveFind(nodes, end, pushVec(path, iter->first), sum+iter->second.timeCost(), minPath, min);
}
}
auto findShortRoute = [](const std::vector<Node> &nodes, int end) {
int min = std::numeric_limits<int>::max();
std::vector<int> minPath;
std::vector<int> path = {1};
recursiveFind(nodes, end, path, 0, minPath, min);
return std::make_pair(minPath, min);
};
std::vector<Node> Traffic::retUpdate(std::vector<std::vector<int>> newRoadsInfo) {
std::vector<Node> retNodes=this->nodes;
for(std::vector<int> roadInfo: newRoadsInfo) {
retNodes[roadInfo[0]-1].disconnect(roadInfo[1]);
retNodes[roadInfo[0]-1].connect(roadInfo[1], roadInfo[2], roadInfo[3]);
retNodes[roadInfo[1]-1].disconnect(roadInfo[0]);
retNodes[roadInfo[1]-1].connect(roadInfo[0], roadInfo[2], roadInfo[3]);
}
return retNodes;
}
auto isInSeq = [](const std::vector<int> &vec, int a, int b) {
for (int i = 0; i < vec.size() - 1; ++i) {
if (vec[i] == a && vec[i + 1] == b)
return true;
}
return false;
};
std::vector<std::pair<int, std::vector<Node>>> Traffic::allNodes(std::vector<int> path) {
std::vector<std::pair<int, std::vector<Node>>> all;
for(int i=0; i<this->roadsInfo.size(); ++i) {
std::vector<std::vector<int>> info=this->roadsInfo;
if(isInSeq(path, this->roadsInfo[i][0], this->roadsInfo[i][1])) {
info[i][3]=this->totalTraffic;
all.push_back(std::make_pair(i, this->retUpdate(info)));
} else {
if(this->roadsInfo[i][3]!=0) {
info[i][3]=0;
all.push_back(std::make_pair(i, this->retUpdate(info)));
}
}
}
return all;
}
std::vector<int> Traffic::mostSensitiveRoad(void) {
std::vector<int> result;
PathAndTime orig=findShortRoute(this->nodes, this->nodeNum);
std::vector<std::pair<int, int>> nodeGap;
std::vector<std::pair<int, std::vector<Node>>> allnodes=this->allNodes(orig.first);
for(std::pair<int, std::vector<Node>> inPair: allnodes) {
PathAndTime change=findShortRoute(inPair.second, this->nodeNum);
if(std::abs(orig.second-change.second)!=0) nodeGap.push_back(std::make_pair(inPair.first, std::abs(orig.second-change.second)));
}
std::sort(nodeGap.begin(), nodeGap.end(), [](std::pair<int, int> ele1, std::pair<int, int> ele2){
return ele1.second<ele2.second;
});
for(auto iter=nodeGap.begin(); iter!=nodeGap.end(); ++iter) result.push_back(iter->first+1);
if(result.size()==0) result.push_back(-1);
return result;
}
int main(void) {
int n1=5;
std::vector<std::vector<int>> roadsInfo1 {
{1, 2, 10, 0},
{2, 4, 8, 0},
{1, 3, 9, 0},
{3, 4, 9, 0},
{3, 5, 10, 6},
{2, 5, 10, 2},
{4, 5, 2, 0}
};
int n2=4;
std::vector<std::vector<int>> roadsInfo2 {
{1, 2, 10, 10},
{2, 3, 10, 10},
{3, 4, 10, 10}
};
int n3=4;
std::vector<std::vector<int>> roadsInfo3 {
{1, 2, 5, 0},
{2, 4, 5, 0},
{1, 3, 5, 0},
{3, 4, 5, 0}
};
int n4=4;
std::vector<std::vector<int>> roadsInfo4 {
{1, 2, 5, 0},
{2, 4, 5, 0},
{1, 3, 5, 0},
{3, 4, 5, 0},
{1, 4, 5, 5}
};
Traffic traffic(n4);
traffic.update(roadsInfo4);
std::vector<int> result=traffic.mostSensitiveRoad();
for(int element: result) std::cout<<element<<' ';
std::cout<<std::endl;
return 0;
}
Fast Move (Lv. 5)
https://school.programmers.co.kr/learn/courses/30/lessons/214294
#include <iostream>
#include <algorithm>
#include <numeric>
#include <utility>
#include <functional>
#include <vector>
#include <map>
#include <string>
class Node {
public:
Node(int num) : num(num) {}
void push(Node* linked);
bool isLinked(int num);
std::vector<int> linkedNum(void);
private:
int num;
std::vector<Node*> linked;
};
void Node::push(Node *linked) { this->linked.push_back(linked); }
bool Node::isLinked(int num) {
for(auto iter=this->linked.begin(); iter!=this->linked.end(); ++iter) if((*iter)->num==num) return true;
return false;
}
std::vector<int> Node::linkedNum(void) {
std::vector<int> result;
for(auto iter=this->linked.begin(); iter!=this->linked.end(); ++iter) result.push_back((*iter)->num);
return result;
}
class Road {
public:
Road(int num);
void updateRoads(std::vector<std::pair<int, int>>);
int minTeleport(void);
private:
void findRoute(std::vector<int>, int, int&);
std::vector<int> teleportAble(std::vector<int> path);
int num;
std::vector<Node> nodes;
};
Road::Road(int num): num(num) {
for(int i=1; i<=num; ++i) this->nodes.push_back(Node(i));
}
void Road::updateRoads(std::vector<std::pair<int, int>> roads) {
for(auto road : roads) {
this->nodes[road.first-1].push(&this->nodes[road.second-1]);
}
}
auto includeAll = [](const std::vector<int> vec, int num) {
std::vector<bool> checker(num, false);
for (auto iter = vec.begin(); iter != vec.end(); ++iter)
checker[*iter - 1] = true;
return std::accumulate(checker.begin(), checker.end(), 0) == num;
};
auto makeNewVecWithAppend = [](const std::vector<int> vec, int value) {
std::vector<int> newVec = vec;
newVec.push_back(value);
return newVec;
};
auto amIbeen = [](const std::vector<int> path, int from) {
std::vector<int> ban;
for (int i = 0; i < path.size() - 1; ++i) {
if (path[i] == from)
ban.push_back(path[i + 1]);
}
return ban;
};
auto isMember = [](const std::vector<int> vec, int value) {
for (auto iter = vec.begin(); iter != vec.end(); ++iter)
if (*iter == value)
return true;
return false;
};
std::vector<int> Road::teleportAble(std::vector<int> path) {
std::vector<int> teleportAble;
std::map<int, int> linkmap;
for(int i=1; i<=this->num; ++i) linkmap[i]=0;
for(int i=0; i<this->nodes.size(); ++i) {
std::vector<int> linked=this->nodes[i].linkedNum();
linkmap[i+1]=linked.size();
}
for(int i=0; i<path.size()-1; ++i) {
linkmap[path[i]]--;
}
for(auto iter=linkmap.begin(); iter!=linkmap.end(); ++iter) {
if(iter->second>0) teleportAble.push_back(iter->first);
}
return teleportAble;
}
void Road::findRoute(std::vector<int> path, int telCount, int& minTel) {
if(includeAll(path, this->num)) {
if(telCount<minTel) minTel=telCount;
return;
}
int now=path.back(), possibleWay=0;
std::vector<int> next=this->nodes[now-1].linkedNum();
std::vector<int> banned=amIbeen(path, now);
for(auto iter=next.begin(); iter!=next.end(); ++iter) {
if(!isMember(banned, *iter)) {
this->findRoute(makeNewVecWithAppend(path, *iter), telCount, minTel);
possibleWay++;
}
}
if(possibleWay==0) {
std::vector<int> teleport=this->teleportAble(path);
for(auto iter=path.begin(); iter!=path.end(); ++iter) {
if(isMember(teleport, *iter)) {
this->findRoute(makeNewVecWithAppend(path, *iter), telCount+1, minTel);
}
}
}
return;
}
int Road::minTeleport(void) {
std::vector<int> been={1};
int minTel=std::numeric_limits<int>::max();
this->findRoute(been, 0, minTel);
return minTel;
}
int main(void) {
int n1=6;
std::vector<std::pair<int, int>> roads1={
{1, 2}, {2, 6}, {2, 4}, {4, 3}, {3, 2}, {3, 5}
};
int n2=5;
std::vector<std::pair<int, int>> roads2={
{1, 2}, {2, 3}, {3, 4}, {4, 5}
};
int n3=8;
std::vector<std::pair<int, int>> roads3={
{6, 4}, {2, 3}, {1, 6}, {4, 5},
{1, 2}, {1, 8}, {3, 7}, {7, 2}
};
int n4=9;
std::vector<std::pair<int, int>> roads4={
{1, 2}, {1, 3}, {1, 4}, {2, 5}, {4, 5},
{5, 6}, {5, 7}, {6, 9}, {7, 9}, {5, 8}
};
int n5=7;
std::vector<std::pair<int, int>> roads5={
{1, 2}, {2, 3}, {3, 4}, {4, 5},
{3, 6}, {1, 7}, {7, 4}
};
Road road(n5);
road.updateRoads(roads5);
int result=road.minTeleport();
std::cout<<"Result: "<<result<<std::endl;
return 0;
}